#pragma once
#ifdef LIT_OGRE_SUPPORT

#ifndef LIT__MESH__HH__
#define LIT__MESH__HH__

#include <LitPrerequisites.h>
#include <LitInitialiser.h>

namespace Lit
{
	class LIT_API ModelDescription;
	class LIT_API MeshDescription
	{
		friend class ModelDescription;

		Lit::String mName;
		Lit::String mMaterial;

		Lit::Vec3	mPosition;
		Lit::Quat	mOrientation;
		Lit::Vec3	mScale;

		bool		mVisible;

	public:
		MeshDescription(){ mVisible = true; }
		virtual ~MeshDescription(){}
		
		const Lit::String& getName() const{ return mName; }
		const Lit::String& getMaterial() const{ return mMaterial; }
		const Lit::Vec3& getPosition() const{ return mPosition; }
		const Lit::Quat& getOrientation() const{ return mOrientation; }
		const Lit::Vec3& getScale() const{ return mScale; }
		bool isVisible() const{ return mVisible; }

		void setName( const String&n ){ mName = n; }
		void setMaterial( const String&m ){ mMaterial = m; }
		void setPosition(const Lit::Vec3&p){ mPosition = p; }
		void setOrientation(const Lit::Quat&o){ mOrientation = o; }
		void setScale(const Lit::Vec3&s){ mScale = s; }
		void setVisible(bool v){ mVisible=v; }

		bool load( std::istream& stream );
		bool save( std::ostream& stream );
	};
	class LIT_API ModelDescription
	{
	public:
		typedef std::unordered_map<String, MeshDescription>		MeshMap;
		typedef MeshMap::iterator										MeshItor;
		typedef MeshMap::const_iterator									MeshConstItor;

	protected:
		Lit::String mName;

		Lit::Vec3	mPosition;
		Lit::Quat	mOrientation;
		Lit::Vec3	mScale;

		MeshMap		mMeshes;
		bool		mVisible;

	public:
		ModelDescription(){ mVisible = true; }
		virtual ~ModelDescription(){}
		
		MeshMap& getMeshes(){ return mMeshes; }
		const MeshMap& getMeshes() const{ return mMeshes; }
		
		MeshItor beginMeshes(){ return mMeshes.begin(); }
		MeshConstItor beginMeshes() const{ return mMeshes.begin(); }
		
		MeshItor endMeshes(){ return mMeshes.end(); }
		MeshConstItor endMeshes() const{ return mMeshes.end(); }

		size_t getNumMeshes() const{ return mMeshes.size(); }
		bool hasMeshes() const{ return !mMeshes.empty(); }

		bool hasMesh( const String &sb ) const{ return mMeshes.find(sb) != mMeshes.end(); }
		MeshDescription* addMesh( const String &sb ){ 
			if( hasMesh( sb ) )
				throw Lit::ItemDuplicate( "SubMesh '"+sb+"'", "Mesh '"+mName+"'", EXC_LOC );
			MeshDescription desc;
			desc.setName( sb );
			mMeshes[sb] = desc;
			return &(mMeshes[sb]);
		}
		void removeMesh( const String &sb ){ 
			if( !hasMesh( sb ) )
				throw Lit::ItemMissing( "SubMesh '"+sb+"'", "Mesh '"+mName+"'", EXC_LOC );
			MeshItor it=mMeshes.find(sb);
			mMeshes.erase( it );
		}
		void clearMeshes( ){ mMeshes.clear(); }

		const Lit::String& getName() const{ return mName; }
		const Lit::Vec3& getPosition() const{ return mPosition; }
		const Lit::Quat& getOrientation() const{ return mOrientation; }
		const Lit::Vec3& getScale() const{ return mScale; }
		bool isVisible() const{ return mVisible; }

		void setName( const String&n ){ mName = n; }
		void setPosition(const Lit::Vec3&p){ mPosition = p; }
		void setOrientation(const Lit::Quat&o){ mOrientation = o; }
		void setScale(const Lit::Vec3&s){ mScale = s; }
		void setVisible(bool v){ mVisible=v; }

		bool load( std::istream& stream );
		bool save( std::ostream& stream );
	};
};

#endif

#endif // IF DEFINED LIT_OGRE_SUPPORT